using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodePlex.SpaceBlock.JobModel;
using CodePlex.Resourceful;
using System.Threading;
using CodePlex.SpaceBlock.UI.Controls.Explore;

namespace CodePlex.SpaceBlock.UI.Controls.Transfers
{
    public partial class TransfersControl : BaseControl
    {


        private static class Actions
        {
            public static readonly string Cancel = "Cancel";
            public static readonly string Restart = "Restart";

            public static readonly string Separator1 = "Separator1";

            public static readonly string ClearSelected = "ClearSelected";
            public static readonly string ClearAll = "ClearAll";
        }

        private JobManager _transferManager;

        private AutoResetEvent _shutdownLoop;
        private BindingList<JobInfoDisplay> _transfers;

        private readonly ActionManager _actions;


        private readonly TextBox _toTextBox;
        private readonly LinkLabel _toLinkLabel;

        public TransfersControl()
        {
            InitializeComponent();

            _actions = new ActionManager(this, UIManager.Instance.SmallImageList, _contextMenu, null);


            _toTextBox = new TextBox();
            _toTextBox.ReadOnly = true;
            _toTextBox.BorderStyle = BorderStyle.None;
            UIUtils.FillWith(_toBox, _toTextBox);

            _toLinkLabel = new LinkLabel();
            _toLinkLabel.LinkBehavior = LinkBehavior.HoverUnderline;

            UIManager.SetHoverStatus(_toLinkLabel, Properties.Messages.Views_Transfers_ExploreTooltip);

            _toLinkLabel.Click += delegate
            {
                JobInfoDisplay d = _transferGrid.SelectedRows[0].DataBoundItem as JobInfoDisplay;
                if (d != null)
                {
                   JobInfo tji =  _transferManager.GetJobInformation(d.JobID);

                   Path toPath = tji.ToPath;

                   UIManager.Instance.MainForm.ShowView<ExploreView>();
                   UIManager.Instance.MainForm.GetView<ExploreView>().ControlStrong.Select(tji.ToFS, tji.ToPath);

                }





            };
            UIUtils.FillWith(_toBox, _toLinkLabel);


            this.ConstructActions();


            this.ConstructGrid();


            this.Disposed += delegate
            {
                _shutdownLoop = new AutoResetEvent(false);
                _transferManager = null;
                _shutdownLoop.WaitOne(TimeSpan.FromSeconds(1), false);
            };
        }


        private void ConstructGrid()
        {
            // workaround designer column auto-add
            while (_transferGrid.Columns.Count > 1)
            {
                _transferGrid.Columns.RemoveAt(1);
            }

            _transferGrid.ReadOnly = true;
           // _transferGrid.ColumnHeadersVisible = false;
            _transferGrid.AllowUserToResizeColumns = false;

            DataGridViewColumn imageColumn = _transferGrid.Columns[0];
            imageColumn.DataPropertyName = "Image";

            DataGridViewColumn captionColumn = _transferGrid.AddColumnText("Caption", 100);
            captionColumn.DataPropertyName = "Caption";
            captionColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            //captionColumn.HeaderText = "";

            DataGridViewColumn descriptionColumn = _transferGrid.AddColumnText("Description", 400);
            descriptionColumn.DataPropertyName = "Description";
            descriptionColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            // descriptionColumn.HeaderText = "";



            _transferGrid.SelectionChanged += delegate
            {
                SyncSelection();
            };
        }

        private void SyncSelection()
        {
            bool onlyOne = _transferGrid.SelectedRows.Count == 1;

            bool showFrom = onlyOne && ((JobInfoDisplay)_transferGrid.SelectedRows[0].DataBoundItem).From != null;
            bool showSize = onlyOne && ((JobInfoDisplay)_transferGrid.SelectedRows[0].DataBoundItem).Size != null;
            bool showTransferred = onlyOne && ((JobInfoDisplay)_transferGrid.SelectedRows[0].DataBoundItem).Transferred != null;



            _sourceLabel.Visible = showFrom;
            _targetLabel.Visible = onlyOne;
            _sizeLabel.Visible = showSize;
            _transferredLabel.Visible = showTransferred;

            _sourceBox.Visible = showFrom;
            _toBox.Visible = onlyOne;
            _sizeBox.Visible = showSize;
            _transferredBox.Visible = showTransferred;

            if (onlyOne)
            {
                object obj = _transferGrid.SelectedRows[0].DataBoundItem;

                _sourceBox.DataBindings.Clear();
                _sizeBox.DataBindings.Clear();
                _transferredBox.DataBindings.Clear();

                _sourceBox.DataBindings.Add("Text", obj, "From");
                _sizeBox.DataBindings.Add("Text", obj, "Size");
                _transferredBox.DataBindings.Add("Text", obj, "Transferred");



                _toTextBox.DataBindings.Clear();
                _toTextBox.DataBindings.Add("Text", obj, "To");
                _toTextBox.DataBindings.Add("Visible", obj, "IsNotComplete");

                _toLinkLabel.DataBindings.Clear();
                _toLinkLabel.DataBindings.Add("Text", obj, "To");
                _toLinkLabel.DataBindings.Add("Visible", obj, "IsComplete");
            }
        }
        private void ConstructActions()
        {

            _actions.NewAction(Actions.Cancel, "Cancel", UIManager.Instance.GetSmallImageListIndex(UIConstants.ImageHints.Delete), null, delegate
            {
                foreach (DataGridViewRow row in _transferGrid.SelectedRows)
                {
                    JobInfoDisplay d = row.DataBoundItem as JobInfoDisplay;

                    UIManager.Instance.JobManager.Cancel(d.JobID);
                }

            });

            _actions.NewAction(Actions.Restart, "Restart", UIManager.Instance.GetSmallImageListIndex(UIConstants.ImageHints.Refresh), null, delegate
           {
               foreach (DataGridViewRow row in _transferGrid.SelectedRows)
               {
                   JobInfoDisplay d = row.DataBoundItem as JobInfoDisplay;

                   UIManager.Instance.JobManager.Restart(d.JobID);
               }

           });


            _actions.NewSeparator(Actions.Separator1);

            _actions.NewAction(Actions.ClearSelected, "Clear", -1, null, delegate
            {
                foreach (DataGridViewRow row in _transferGrid.SelectedRows)
                {
                    JobInfoDisplay d = row.DataBoundItem as JobInfoDisplay;

                    UIManager.Instance.JobManager.Clear(d.JobID);
                }
            });
            _actions.NewAction(Actions.ClearAll, "Clear Finished", -1, null, delegate
            {
                UIManager.Instance.JobManager.ClearFinished();

            });


            _contextMenu.Opening += delegate
            {

                List<JobInfoDisplay> selectedJobs = new List<JobInfoDisplay>(Utils.ConvertAll<DataGridViewRow, JobInfoDisplay>(_transferGrid.SelectedRows, delegate(DataGridViewRow item)
                {
                    return item.DataBoundItem as JobInfoDisplay;

                }));

                _actions.SetEnabled(Actions.Cancel, selectedJobs.Count > 0 && selectedJobs.TrueForAll(JobInfoDisplay.IsRunning));
                _actions.SetEnabled(Actions.ClearSelected, selectedJobs.Count > 0 && selectedJobs.TrueForAll(JobInfoDisplay.IsFinished));
                _actions.SetEnabled(Actions.Restart, selectedJobs.Count > 0 && selectedJobs.TrueForAll(JobInfoDisplay.IsFinished));
            };


            _actions.BindTo(_transferGrid);
        }

        private void RefreshLoop()
        {
            try
            {

                Dictionary<JobStatus, Image> icons = new Dictionary<JobStatus, Image>();
                icons[JobStatus.Running] = UIManager.Instance.GetSmallImage(UIConstants.ImageHints.Transfer);
                icons[JobStatus.Completed] = UIManager.Instance.GetSmallImage(UIConstants.ImageHints.Valid);
                icons[JobStatus.Failed] = UIManager.Instance.GetSmallImage(UIConstants.ImageHints.Invalid);
                icons[JobStatus.Cancelled] = UIManager.Instance.GetSmallImage(UIConstants.ImageHints.Delete);

                while (_transferManager != null)
                {

                    if (this.Visible)
                    {
                        List<JobInfo> infos = new List<JobInfo>(_transferManager.GetJobInformation());

                        this.InDisplay(delegate
                        {
                            int newIndex = 0;
                            foreach (JobInfo info in infos)
                            {
                                int currentIndex = _transfers.IndexOf(new JobInfoDisplay(info.JobID));

                                JobInfoDisplay d;
                                bool insert = false;
                                if (currentIndex == -1)
                                {
                                    d = new JobInfoDisplay(info.JobID);
                                    insert = true;
                                }
                                else if (currentIndex != newIndex)
                                {
                                    d = _transfers[currentIndex];
                                    _transfers.RemoveAt(currentIndex);
                                    insert = true;
                                }
                                else
                                {
                                    d = _transfers[currentIndex];
                                }

                                d.Image = SpaceBlockUtils.SafeGet(icons, info.Status);
                                d.Status = info.Status;
                                d.Caption = info.Caption;
                                d.Description = info.Description;

                                d.From = info.From;
                                d.To = info.To;
                                d.Size = info.Size;
                                d.Transferred = info.Transferred;

                                d.Speed = info.Speed;
                                d.Progress = info.Progress;

                                if (insert)
                                {
                                    _transfers.Insert(newIndex, d);
                                }

                                newIndex++;
                            }

                            while (_transfers.Count > newIndex)
                            {
                                _transfers.RemoveAt(_transfers.Count - 1);
                            }

                        });
                    
                    }
                   
                    Thread.Sleep(300);
                }

                Utils.TraceWriteLine("Exiting RefreshLoop()");
                _shutdownLoop.Set();
            }
            catch (Exception ex)
            {
                this.HandleException(ex);
            }
        }



        public void Initialize(JobManager transferManager)
        {
            _transfers = new BindingList<JobInfoDisplay>();

            _transferManager = transferManager;

            _transferGrid.DataSource = _transfers;
            _transferGrid.Columns.Remove(_transferGrid.Columns["JobID"]);
            _transferGrid.Columns.Remove(_transferGrid.Columns["Status"]);

            _transferGrid.Columns.Remove(_transferGrid.Columns["From"]);
            _transferGrid.Columns.Remove(_transferGrid.Columns["To"]);
            _transferGrid.Columns.Remove(_transferGrid.Columns["Size"]);
            _transferGrid.Columns.Remove(_transferGrid.Columns["Transferred"]);

            _transferGrid.Columns.Remove(_transferGrid.Columns["IsComplete"]);
            _transferGrid.Columns.Remove(_transferGrid.Columns["IsNotComplete"]);

            _transferGrid.Columns.Remove(_transferGrid.Columns["Progress"]);
            DataGridViewColumn r = _transferGrid.AddProgressColumn("Progress");
            r.DataPropertyName = "Progress";
            Operation loop = RefreshLoop;
            loop.BeginInvoke(null, null);

            SyncSelection();


        }

    


        public void Select(Guid jobID)
        {
            Fn<bool> findAndSelect = delegate
            {
                foreach (DataGridViewRow r in _transferGrid.Rows)
                {
                    JobInfoDisplay d = r.DataBoundItem as JobInfoDisplay;
                    if (d.JobID == jobID)
                    {
                        _transferGrid.ClearSelection();
                        r.Selected = true;
                        return true;
                    }
                }
                return false;
            };
            if (!findAndSelect())
            {
                _transferGrid.RowsAdded += delegate
                {
                    findAndSelect();
                };
            }



        }
    }
}

